
`include "Definitons.sv"
`timescale 1ns / 1ps
module SimTop(
    input                               clock                      ,
    input                               reset                      ,

    input              [  63:0]         io_logCtrl_log_begin       ,
    input              [  63:0]         io_logCtrl_log_end         ,
    input              [  63:0]         io_logCtrl_log_level       ,
    input                               io_perfInfo_clean          ,
    input                               io_perfInfo_dump           ,

    output                              io_uart_out_valid          ,
    output             [   7:0]         io_uart_out_ch             ,
    output                              io_uart_in_valid           ,
    input              [   7:0]         io_uart_in_ch               
);

// if_stage
wire                   [  63:0]         pc                         ;
wire                   [  31:0]         inst                       ;
wire                                    rst_n                      ;
reg                                     IM_ready                   ;
wire                                    intr_ready                 ;
wire                                    IM_vld                     ;
wire                   [  63:0]         IM_addr                    ;
reg                    [  31:0]         IM_rdata                   ;
wire                   [  63:0]         ram_addr                   ;
wire                   [  63:0]         DM_wdata                   ;
wire                   [   7:0]         DM_wstrb                   ;
wire                   [  63:0]         DM_rdata                   ;
wire                   [  63:0]         intr_rdata                 ;
wire                                    DM_valid                   ;
wire                                    DM_ready                   ;
wire                   [  63:0]         DM_addr                    ;
wire                   [  63:0]         mem_addr                   ;
wire                   [  63:0]         data_addr                  ;
wire                   [  63:0]         mem_data                   ;
wire                   [  63:0]         instr_addr                 ;
reg                    [  63:0]         pc_r                       ;
reg                    [  31:0]         inst_r                     ;
reg                                     inst_vld_r                 ;
reg                                     cmt_wen_r                  ;
reg                    [   7:0]         cmt_wdest_r                ;
reg                    [  63:0]         cmt_wdata_r                ;
reg                    [   2:0]         cmt_intr_r                 ;
reg                                     skip_r                     ;
reg                    [   2:0]         cnt_rst                    ;
wire                                    interrupt_soft             ;
wire                                    interrupt_timer            ;
wire                                    interrupt_ext              ;
reg                    [   3:0]         skip_mem                   ;
reg                                     vld_flag  ;
reg intr_sel;
localparam ram_pipe = 1;
reg [64-1:0] ram_dataa [ram_pipe-1:0];
reg  rdy [ram_pipe-1:0];
assign DM_rdata = intr_sel ? ram_dataa[ram_pipe-1] : intr_rdata;
assign DM_ready = rdy[ram_pipe-1];
genvar                 j;
assign pc = IM_addr;
assign mem_addr = DM_addr[30:0];
assign rst_n = !(|cnt_rst);
always@(posedge clock)begin
  if(reset)
    cnt_rst <= 1;
  else
  if(|cnt_rst)
    cnt_rst <= cnt_rst + 1;
end
  generate  begin:delay_n

      for( j=0; j<ram_pipe; j=j+1)
        if(j == 0)begin:get_value
          always @(posedge clock)begin
            ram_dataa[0] <= mem_data;  
            rdy[0]       <= DM_valid;
          end  
        end
        else begin:delay
          always @(posedge clock)begin
            ram_dataa[j] <= ram_dataa[j-1];
            rdy[j]  <= rdy[j-1];
          end
        end
    end
  endgenerate
always@(posedge clock, negedge rst_n)begin
  if(!rst_n)begin
    IM_ready <= 1'b0;
    intr_sel <= 1'b0;
    skip_mem <= 1'b0;
  end
  else begin
    IM_ready <= IM_vld;
    intr_sel <= DM_addr[31];
    skip_mem[0] <= DM_valid && !DM_addr[31];
    skip_mem[1] <= skip_mem[0];
    skip_mem[2] <= skip_mem[1];
  end
end


always@(posedge clock)begin
  if(!rst_n)
    IM_rdata <= 'd0;
  else
    IM_rdata <= inst;
end
    Core_y top_inst
    (
    .clk                               (clock                     ),
    .rst_n                             (rst_n                     ),
    .IB_rdy                             (IM_ready                  ),
    .IB_vld                             (IM_vld                    ),
    .DB_rdy                             (DM_ready                  ),
    .IB_data                            (IM_rdata                  ),
    .IB_addr                            (IM_addr                   ),
    .DB_wdata                           (DM_wdata                  ),
    .DB_wstrb                           (DM_wstrb                  ),
    .DB_vld                             (DM_valid                  ),
    .DB_addr                            (DM_addr                   ),
    .DB_rdata                           (DM_rdata                  ),
    .interrupt_soft                    (interrupt_soft            ),
    .interrupt_timer                   (interrupt_timer           ),
    .interrupt_ext                     (interrupt_ext             ) 
    );
RAM_1W2R RAM_INST(
    .clk                               (clock                     ),
    .inst_addr                         (pc                        ),
    .inst_ena                          (1                         ),
    .inst                              (inst                      ),
    .mem_wr_en                         (DM_valid                  ),
    .mem_rd_en                         (!DM_wstrb                 ),
    .byte_enble                        (DM_wstrb                  ),
    .mem_addr                          (mem_addr                  ),
    .mem_wr_data                       (DM_wdata                  ),
    .mem_rd_data                       (mem_data                  ) 
);
pliclint interrupt(
    .clk                               (clock                     ),
    .rst_n                             (rst_n                     ),
    .rdy                               (intr_ready                ),
    .wdata                             (DM_wdata                  ),
    .wstrb                             (DM_wstrb                  ),
    .vld                               (DM_valid && !DM_addr[31]  ),
    .addr                              (DM_addr                   ),
    .rdata                             (intr_rdata                ),
    .interrupt_soft                    (interrupt_soft            ),
    .interrupt_timer                   (interrupt_timer           ),
    .interrupt_ext                     (interrupt_ext             ) 
    );
always@(posedge clock)begin
  if(!rst_n)
    vld_flag <= 'd0;
  else
  if(top_inst.I_vld_wb)
    vld_flag <= 'd1;
  else   
  if(top_inst.interrupt_wb)
    vld_flag <= 'd0;
end
always @(posedge clock) begin
  if(top_inst.I_vld_wb || top_inst.interrupt_wb)begin
    skip_r <= (top_inst.instr_wb[31:20] == 12'hb00 &&  top_inst.instr_wb[6:2] == 5'b11100) || top_inst.instr_wb == 32'h7b || skip_mem[1];
    pc_r <= top_inst.pc_wb;
    inst_r <= top_inst.instr_wb;
    // inst_vld_r <= vld_flag && top_inst.I_vld_wb;
    cmt_wen_r <= top_inst.Wenreg_wb;
    cmt_wdest_r <= top_inst.rd_addr_wb;
    cmt_wdata_r <= top_inst.rd_wb;
  end
  if(top_inst.interrupt_wb)
    cmt_intr_r <= 1;
  else  
  if(top_inst.I_vld_wb)
    cmt_intr_r <= 0;
end
// Difftest
reg                                     cmt_wen                    ;
reg                    [   7:0]         cmt_wdest                  ;
reg                    [  63:0]         cmt_wdata                  ;
reg                    [  63:0]         cmt_pc                     ;
reg                    [  31:0]         cmt_inst                   ;
reg                                     cmt_valid                  ;
reg                                     trap                       ;
reg                    [   7:0]         trap_code                  ;
reg                    [  63:0]         cycleCnt                   ;
reg                    [  63:0]         instrCnt                   ;
reg                                     cmt_skip                   ;
reg                    [63:0]           cmt_mtvec                  ;
reg                    [63:0]           cmt_mcause                 ;
reg                    [63:0]           cmt_mepc                   ;
reg                    [63:0]           cmt_mtval                  ;
reg                    [63:0]           cmt_mstatus                ;
reg                    [63:0]           cmt_mip                    ;
reg                    [  63:0]         cmt_mie                    ;
reg                    [  63:0]         cmt_mscratch               ;
reg                    [  63:0]         cmt_intrno                 ;
reg                    [63:0]           cmt_sstatus                ;
reg [63:0] regs_diff [0 : 31];
integer                 i;
always @(negedge clock) begin
  if (reset) begin
    {cmt_wen, cmt_wdest, cmt_wdata, cmt_pc, cmt_inst, cmt_valid, trap, trap_code, cycleCnt, instrCnt} <= 0;
  end
  else if (~trap) begin
    cmt_wen <= cmt_wen_r;
    cmt_wdest <= cmt_wdest_r;
    cmt_wdata <= cmt_wdata_r;
    cmt_valid <= vld_flag && (top_inst.I_vld_wb || top_inst.interrupt_wb);// 
    cmt_pc <= pc_r;
    cmt_inst <= inst_r;
    trap <= inst_r[6:0] == 7'h6b;
    trap_code <= 0;//top_inst.x[10][7:0];
    cycleCnt <= cycleCnt + 1;
    instrCnt <= instrCnt + top_inst.I_vld_wb;
    // instrCnt <= instrCnt + inst_vld_r;
    cmt_skip <= skip_r;
    // cmt_mtvec <= top_inst.csr.mtvec;
    // cmt_mcause <= top_inst.csr.mcause;
    // cmt_mepc <= top_inst.csr.mepc;
    // cmt_mtval <= top_inst.csr.mtval;
    // cmt_mstatus <= top_inst.csr.mstatus;
    // cmt_sstatus <= top_inst.sstatus;
    // cmt_mip <= top_inst.csr.mip;
    // cmt_mie <= top_inst.csr.mie;
    // cmt_mscratch <= top_inst.csr.mscratch;
    cmt_mtvec <= top_inst.csr_reg_wb.mtvec;
    cmt_mcause <= top_inst.csr_reg_wb.mcause;
    cmt_mepc <= top_inst.csr_reg_wb.mepc;
    // cmt_mtval <= top_inst.csr_reg_wb.mtval;
    cmt_mstatus <= top_inst.csr_reg_wb.mstatus;
    cmt_sstatus <= top_inst.csr_reg_wb.mstatus & 64'h80000003_000de122;
    cmt_mip <= top_inst.csr_reg_wb.mip;
    cmt_mie <= top_inst.csr_reg_wb.mie;
    cmt_mscratch <= top_inst.csr_reg_wb.mscratch;
    cmt_intrno <= cmt_intr_r&&top_inst.I_vld_wb ? 7:0;
    for(i =1; i<32;i=i+1)
        regs_diff[i] <= top_inst.x[i];
  end
end
DifftestInstrCommit DifftestInstrCommit(
    .clock                             (clock                     ),
    .coreid                            (0                         ),
    .index                             (0                         ),
    .valid                             (cmt_valid                 ),
    .pc                                (cmt_pc                    ),
    .instr                             (cmt_inst                  ),
    .skip                              (cmt_skip                  ),
    .isRVC                             (0                         ),
    .scFailed                          (0                         ),
    .wen                               (cmt_wen                   ),
    .wdest                             (cmt_wdest                 ),
    .wdata                             (cmt_wdata                 )
);
DifftestArchEvent intrcommit(
    .clock                             (clock                     ),
    .coreid                            (0                         ),
    .intrNO                            (cmt_intrno                ),
    .cause                             (0                         ),
    .exceptionPC                       (cmt_pc                    ),
    .exceptionInst                     (0                         ) 
);
DifftestArchIntRegState DifftestArchIntRegState (
    .clock                             (clock                     ),
    .coreid                            (0                         ),
    .gpr_0                             (0                         ),
    .gpr_1                             (regs_diff[1]              ),
    .gpr_2                             (regs_diff[2]              ),
    .gpr_3                             (regs_diff[3]              ),
    .gpr_4                             (regs_diff[4]              ),
    .gpr_5                             (regs_diff[5]              ),
    .gpr_6                             (regs_diff[6]              ),
    .gpr_7                             (regs_diff[7]              ),
    .gpr_8                             (regs_diff[8]              ),
    .gpr_9                             (regs_diff[9]              ),
    .gpr_10                            (regs_diff[10]             ),
    .gpr_11                            (regs_diff[11]             ),
    .gpr_12                            (regs_diff[12]             ),
    .gpr_13                            (regs_diff[13]             ),
    .gpr_14                            (regs_diff[14]             ),
    .gpr_15                            (regs_diff[15]             ),
    .gpr_16                            (regs_diff[16]             ),
    .gpr_17                            (regs_diff[17]             ),
    .gpr_18                            (regs_diff[18]             ),
    .gpr_19                            (regs_diff[19]             ),
    .gpr_20                            (regs_diff[20]             ),
    .gpr_21                            (regs_diff[21]             ),
    .gpr_22                            (regs_diff[22]             ),
    .gpr_23                            (regs_diff[23]             ),
    .gpr_24                            (regs_diff[24]             ),
    .gpr_25                            (regs_diff[25]             ),
    .gpr_26                            (regs_diff[26]             ),
    .gpr_27                            (regs_diff[27]             ),
    .gpr_28                            (regs_diff[28]             ),
    .gpr_29                            (regs_diff[29]             ),
    .gpr_30                            (regs_diff[30]             ),
    .gpr_31                            (regs_diff[31]             ) 
);

DifftestTrapEvent DifftestTrapEvent(
    .clock                             (clock                     ),
    .coreid                            (0                         ),
    .valid                             (trap                      ),
    .code                              (trap_code                 ),
    .pc                                (cmt_pc                    ),
    .cycleCnt                          (cycleCnt                  ),
    .instrCnt                          (instrCnt                  ) 
);

DifftestCSRState DifftestCSRState(
    .clock                             (clock                     ),
    .coreid                            (0                         ),
    .priviledgeMode                    (3                         ),
    .mstatus                           (cmt_mstatus               ),
    .sstatus                           (cmt_sstatus               ),
    .mepc                              (cmt_mepc                  ),
    .sepc                              (0                         ),
    .mtval                             (cmt_mtval                 ),
    .stval                             (0                         ),
    .mtvec                             (cmt_mtvec                 ),
    .stvec                             (0                         ),
    .mcause                            (cmt_mcause                ),
    .scause                            (0                         ),
    .satp                              (0                         ),
    .mip                               (cmt_mip                   ),
    .mie                               (cmt_mie                   ),
    .mscratch                          (cmt_mscratch              ),
    .sscratch                          (0                         ),
    .mideleg                           (0                         ),
    .medeleg                           (0                         ) 
);

DifftestArchFpRegState DifftestArchFpRegState(
    .clock                             (clock                     ),
    .coreid                            (0                         ),
    .fpr_0                             (0                         ),
    .fpr_1                             (0                         ),
    .fpr_2                             (0                         ),
    .fpr_3                             (0                         ),
    .fpr_4                             (0                         ),
    .fpr_5                             (0                         ),
    .fpr_6                             (0                         ),
    .fpr_7                             (0                         ),
    .fpr_8                             (0                         ),
    .fpr_9                             (0                         ),
    .fpr_10                            (0                         ),
    .fpr_11                            (0                         ),
    .fpr_12                            (0                         ),
    .fpr_13                            (0                         ),
    .fpr_14                            (0                         ),
    .fpr_15                            (0                         ),
    .fpr_16                            (0                         ),
    .fpr_17                            (0                         ),
    .fpr_18                            (0                         ),
    .fpr_19                            (0                         ),
    .fpr_20                            (0                         ),
    .fpr_21                            (0                         ),
    .fpr_22                            (0                         ),
    .fpr_23                            (0                         ),
    .fpr_24                            (0                         ),
    .fpr_25                            (0                         ),
    .fpr_26                            (0                         ),
    .fpr_27                            (0                         ),
    .fpr_28                            (0                         ),
    .fpr_29                            (0                         ),
    .fpr_30                            (0                         ),
    .fpr_31                            (0                         ) 
);

endmodule

`include "Definitons.sv"
`timescale 1ns / 1ps
module RAM_1W2R(
    input                               clk                        ,
    
    input              [  63:0]         inst_addr                  ,
    input                               inst_ena                   ,
    output             [  31:0]         inst                       ,

    // DATA PORT
    input                               mem_wr_en                  ,
    input                               mem_rd_en                  ,
    input              [   7:0]         byte_enble                 ,
    input              [  63:0]         mem_addr                   ,
    input              [  63:0]         mem_wr_data                ,
    output reg         [  63:0]         mem_rd_data                 
);
    wire[  63:0] inst_2 = ram_read_helper(inst_ena,{3'b000,(inst_addr-64'h0000_0000_8000_0000)>>3});

    assign inst = inst_addr[2] ? inst_2[63:32] : inst_2[31:0];

    // DATA PORT 
    wire [  63:0] now_rd_data = ram_read_helper(mem_rd_en, mem_addr >> 3);
    
    assign mem_rd_data = now_rd_data;//mem_addr[2] ? {now_rd_data[63:0]} : {now_rd_data[31:0],now_rd_data[63:32]};

    // 掩码转换
    wire [  63:0] wmask = { {8{byte_enble[7]}},
                                {8{byte_enble[6]}},
                                {8{byte_enble[5]}},
                                {8{byte_enble[4]}},
                                {8{byte_enble[3]}},
                                {8{byte_enble[2]}},
                                {8{byte_enble[1]}},
                                {8{byte_enble[0]}}};

    wire [  63:0]wr_data = mem_wr_data;

    always @(posedge clk) begin
        ram_write_helper(mem_addr>>3, wr_data, wmask, mem_wr_en);
    end

endmodule
